package com.my.geojson.test.wfs.xmlGenerate;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.my.geojson.test.wfs.exception.GeoXmlQlException;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.Map;

/**
 * @author qinlei
 * @description todo
 * @date 2021/10/21 16:44
 */
public abstract class WFSTXmlGenerate {

    public static final String INSERT_METHOD = "Insert";
    public static final String UPDATE_METHOD = "Update";
    public static final String DELETE_METHOD = "Delete";

    private Document document;

    public Document getDocument() {
        return document;
    }

    public WFSTXmlGenerate() {
        document = DocumentHelper.createDocument();
        Element wfs = document.addElement("wfs:Transaction");
        wfs.addAttribute("version", "1.0.0");
        wfs.addAttribute("service", "WFS");
        //新增
        wfs.addNamespace("wfs", "http://www.opengis.net/wfs");
//        wfs.addNamespace("xmlns:wfs", "http://www.opengis.net/wfs");
        wfs.addNamespace("ogc", "http://www.opengis.net/ogc");
//        wfs.addNamespace("xmlns:ogc", "http://www.opengis.net/ogc");
        //新增
//        wfs.addNamespace("opengis", "http://10.137.42.66:8009/test");
//        wfs.addNamespace("fes", "http://www.opengis.net/fes/2.0");
//        //原有
//        wfs.addNamespace("gml", "http://www.opengis.net/gml");
//        wfs.addNamespace("xsi", "http://www.opengis.net/xsi");
//        wfs.addAttribute("xsi:schemaLocation", "http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd");
    }

    /**
     * 生成xml方法
     * 版本修改以后xml格式有变换具体参考
     * http://amap.zju.edu.cn/geoserver/web/wicket/bookmarkable/org.geoserver.web.demo.DemoRequestsPage?0
     */
    public abstract Document createXml(String businessId,String username, String typeName, String wfsPath, Map<String, Object> variables, Map<String, Object> params)throws GeoXmlQlException;

    /**
     * 创建k-v的节点
     *
     * @param property
     * @param k
     * @param v geom时,该v为jsonObject
     * @param workspace 工作空间(geom需要 其余设置为空)
     */
    void createKVNode(Element property, String k, Object v, String workspace) throws GeoXmlQlException {
        if (StringUtils.isBlank(workspace)) {
            Element key = property.addElement("wfs:Name");
//            Element key = property.addElement("wfs:ValueReference");
            key.setText(k);
            Element value = property.addElement("wfs:Value");
            if (v != null)
                value.setText(v.toString());
            return;
        }
        //这里因为workspace一直为null 所以暂时无用 2022年6月14日15:25:18
        Element element = property.addElement(workspace + ":" + k);
        if(v==null)
            return;
        JSONObject valueJson = JSON.parseObject(JSONObject.toJSONString(v));
        String type = valueJson.getString("type");
        if("general".equals(type) && v!=null){
            element.setText(valueJson.getString("value"));
        }else if("MultiLineString".equals(type)){
            String coordinates = valueJson.getString("coordinates");
            this.createMultiLineEle(element,type,coordinates);
        }else if("Point".equals(type)){
            String coordinates = valueJson.getString("coordinates");
            this.createPointEle(element,type,coordinates);
        }else{

        }

    }

    private void createMultiLineEle(Element element,String type,String coordinates){
        Element multiLineString = createGeomEle(element,type);
        Element lineStringMember = multiLineString.addElement("gml:lineStringMember");
        Element LineString = lineStringMember.addElement("gml:LineString");
        createCoorEle(LineString,coordinates);
    }

    private void createPointEle(Element element,String type,String coordinates){
        Element point = createGeomEle(element,type);
        createCoorEle(point,coordinates);
    }

    private Element createGeomEle(Element element, String type){
        Element point = element.addElement("gml:" + type);
        point.addAttribute("srsName", "http://www.opengis.net/gml/srs/epsg.xml#4326");
        return point;
    }

    private void createCoorEle(Element toPoint,String coordinates){
        Element coor = toPoint.addElement("gml:coordinates");
        coor.addAttribute("decimal", ".");
        coor.addAttribute("cs", ",");
        coor.addAttribute("ts", ";");
        coor.setText(coordinates);
    }


    public void createUpdateNode(Element element, String typeName, Map<String,Object> variables, Map<String,Object> params) throws GeoXmlQlException {
        Element updateNode = element.addElement("wfs:"+UPDATE_METHOD);
        updateNode.addAttribute("typeName",typeName);
        for (Map.Entry<String, Object> entry : variables.entrySet()) {
            Element property = updateNode.addElement("wfs:Property");
            this.createKVNode(property,entry.getKey(),entry.getValue(),null);
        }
        createFilterNode(updateNode,typeName.split(":")[0],params);
    }

    public void createInsertNode(String wfsPath,Element element, String typeName, Map<String,Object> variables) throws GeoXmlQlException {
        String[] typeSplit = typeName.split(":");
        String workspace = typeSplit[0];
        element.addNamespace(workspace,"http://"+workspace);
        element.addAttribute("xsi:schemaLocation",element.attributeValue("xsi:schemaLocation")+" http://"+workspace+" "
                + wfsPath+"/DescribeFeatureType?typename="+typeName);
        Element insertNode = element.addElement("wfs:"+INSERT_METHOD);
        Element property = insertNode.addElement(typeName);
        for (Map.Entry<String, Object> entry : variables.entrySet()) {
//            this.createKVNode(property,entry.getKey(),entry.getValue(),workspace);
            this.createKVNode(property,entry.getKey(),entry.getValue(),null);
        }
//        createFilterNode(element,workspace,params);
    }

    public void createDeleteNode(Element element, String typeName, Map<String, Object> variables, Map<String, Object> params) throws GeoXmlQlException {
        Element deleteNode = element.addElement("wfs:" + DELETE_METHOD);
        deleteNode.addAttribute("typeName", typeName);
        createFilterNode(deleteNode,typeName.split(":")[0], params);
    }

    /**
     * 创建fid过滤器节点
     * 为了安全性考虑 fids不允许非空 目前只提供id的过滤
     *
     * @param element
     * @param params
     */
    void createFilterNode(Element element,String workspace, Map<String, Object> params) throws GeoXmlQlException {
        if (params == null || params.isEmpty()) {
            return;
        }
        Element filter = element.addElement("ogc:Filter");



//        for (Map.Entry<String, Object> objectEntry : params.entrySet()) {
//            Element property = filter.addElement("ogc:PropertyIsEqualTo");
//            Element nameEle = property.addElement("ogc:PropertyName");
//            nameEle.setText(workspace+":"+objectEntry.getKey());
//            Element literalEle = property.addElement("ogc:Literal");
//            literalEle.setText(objectEntry.getValue() == null ? null : objectEntry.getValue().toString());
//        }

        Element property = filter.addElement("ogc:FeatureId");
        for (Map.Entry<String, Object> objectEntry : params.entrySet()) {
//            property.addAttribute("fid","test.43");
            property.addAttribute(objectEntry.getKey(),objectEntry.getValue().toString());
//            filter.addElement("fes:ResourceId "+objectEntry.getKey()
//            + "=\""+objectEntry.getValue().toString()+"\"");
        }
    }

}

